package arith;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
//import java.text.DecimalFormat;
//import java.util.Map;
import java.lang.String;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTreeNodeStream;

import uk.ac.ed.ph.snuggletex.SnuggleEngine;
import uk.ac.ed.ph.snuggletex.SnuggleInput;
import uk.ac.ed.ph.snuggletex.SnuggleSession;

import arith.BasicArithmeticEquParser.evaluator_return;
import arith.BasicArithmeticEquParser.problem_return;

public class EquationTest {
	
	public static void main(String[] args) throws RecognitionException, IOException{
		EquationTest test = new EquationTest();
		
		test.inputTest();

	}
	
	public void inputTest() throws IOException, RecognitionException{
		 InputStreamReader iStream = new InputStreamReader(System.in) ;
		 BufferedReader bRead = new BufferedReader(iStream) ;
		 System.out.println("Enter problem type:");
		 String type = bRead.readLine();
		 Problem prob = runTest(type);
		 System.out.println("Enter solution:");
		 String answer = bRead.readLine();
		 if(prob.id == 0){
			 int s = Integer.parseInt(answer);
			 if(s == (Double) prob.getSolution()){
				 System.out.println("Congratulations! You solved the problem correctly!");
			 }else{
				 System.out.println("Incorrect Response");
			 }
		 }
	}
	
	public void recognitionTest() throws RecognitionException{
		System.out.println("<add>");
		runTest("<add>");
		System.out.println("\n<sub>");
		runTest("<sub>");
		System.out.println("\n<mult>");
		runTest("<mult>");
		System.out.println("\n<div>");
		runTest("<div>");
		System.out.println("\n<fracAdd>");
		runTest("<fracAdd>");
		System.out.println("\n<fracSub>");
		runTest("<fracSub>");
		System.out.println("\n<fracMult>");
		runTest("<fracMult>");
		System.out.println("\n<fracDiv>");
		runTest("<fracDiv>");
		System.out.println("\nExpontent Addition:");
		runTest("<expAdd>");
		System.out.println("\nExpontent Subtraction:");
		runTest("<expSub>");
		System.out.println("\nExpontent Multiplication:");
		runTest("<expMult>");
		System.out.println("\nExpontent Division:");
		runTest("<expDiv>");
		System.out.println("\nFactoring:");
		probFromTemplate("<factor>");
		System.out.println("\nGCF:");
		probFromTemplate("<gcf>");
		System.out.println("\nLCM:");
		probFromTemplate("<lcm>");
		System.out.println("\nAssociative Property:");
		probFromTemplate("<assoc>");
		System.out.println("\nDistributive Property:");
		probFromTemplate("<dist>");
	}
	
	/*public void runTest(Problem prob) throws RecognitionException{
		//Parse prob's template and problem
		String equ = prob.getTemplate();
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		evaluator_return evaluator = parser.evaluator();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(evaluator.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		
		//Prints out the tree
		//System.out.println(evaluator.tree.toStringTree());
		
		//The result of the expression
		Output result = walker.evaluator();
		
		/*
		//The values of each variable
		Map<String, Double> variables = walker.variables;
		
		//Create DecimalFormat object
		DecimalFormat df = new DecimalFormat("0.##");

		//Convert the template to the problem
	    String tempToEqu[] = new String[equ.length()];
	    for(int i=0; i < tempToEqu.length; i++){
	    	tempToEqu[i] = "" + equ.charAt(i);
	    	if(variables.containsKey(tempToEqu[i])){
	    		tempToEqu[i] = "" + df.format(variables.get(tempToEqu[i])); 
	    	}
	    }
	    String tempToEquation = "";
	    for(int j = 0; j < tempToEqu.length; j++){
	    	tempToEquation = tempToEquation + tempToEqu[j];
	    }
	    //Add the problem and solution to the Problem object
	    prob.setProblem(tempToEquation);
		
		if(result == null){
			System.out.println("result is null");
		}
	    if(result.id == 0){
	    	//Solution is a double
	    	prob.setProblem(result.nSolution.prob);
	    	prob.setSolution(result.nSolution.number);
	    }else if(result.id == 1){
	    	//Solution is a fraction
	    	prob.setProblem(result.fSolution.prob);
	    	prob.setSolution(result.fSolution);
	    }else if(result.id == 2){
	    	prob.setProblem(result.eSolution.prob);
	    	prob.setSolution(result.eSolution);
	    }else if(result.id == 3){
	    	prob.setProblem(result.factorSolution.prob.getProblem());
	    	prob.setSolution(result.factorSolution.factors);
	    	
	    }else if(result.id == 4){
	    	prob.setProblem(result.propSolution.prob.getProblem());
	    	prob.setSolution(result.propSolution.prob.stringSolution);
	    }
	    
	    //Print out the problem
	    System.out.println(prob.toString());
	    
	    //Print out the MathML of the problem
	    //System.out.println("MathML:" + makeImage(prob));
	    
	}*/
	
	public Problem runTest(Problem prob) throws RecognitionException{
		//Parse prob's template and problem
		String equ = prob.getTemplate();
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		evaluator_return evaluator = parser.evaluator();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(evaluator.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		
		//Prints out the tree
		//System.out.println(evaluator.tree.toStringTree());
		
		//The result of the expression
		Output result = walker.evaluator();
		
		if(result == null){
			System.out.println("result is null");
		}
	    if(result.id == 0){
	    	//Solution is a double
	    	prob.setProblem(result.nSolution.prob);
	    	prob.setSolution(result.nSolution.number);
	    }else if(result.id == 1){
	    	//Solution is a fraction
	    	prob.setProblem(result.fSolution.prob);
	    	prob.setSolution(result.fSolution);
	    }else if(result.id == 2){
	    	prob.setProblem(result.eSolution.prob);
	    	prob.setSolution(result.eSolution);
	    }else if(result.id == 3){
	    	prob.setProblem(result.factorSolution.prob.getProblem());
	    	prob.setSolution(result.factorSolution.factors);
	    	
	    }else if(result.id == 4){
	    	prob.setProblem(result.propSolution.prob.getProblem());
	    	prob.setSolution(result.propSolution.prob.stringSolution);
	    }else{
	    	prob = null;
	    }
	    
	    //Print out the problem
	    System.out.println(prob.toString());
	    
	    //Print out the MathML of the problem
	    //System.out.println("MathML:" + makeImage(prob));
	    return prob;
	    
	}
	
	public Problem runTest(String equ) throws RecognitionException{
		CharStream charStream = new ANTLRStringStream(equ);
		BasicArithmeticEquLexer lexer = new BasicArithmeticEquLexer(charStream);
		TokenStream tokenStream = new CommonTokenStream(lexer);
		BasicArithmeticEquParser parser = new BasicArithmeticEquParser(tokenStream);
		problem_return problem;
		problem = parser.problem();
		CommonTreeNodeStream nodeStream = new CommonTreeNodeStream(problem.tree);
		GrammarEvaluator walker = new GrammarEvaluator(nodeStream);
		Problem prob = walker.problem();
		return runTest(prob);
	}
	
	public void probFromTemplate(String temp) throws RecognitionException{
		runTest(new Problem(temp));
	}
	
	public String makeImage(Problem problem){
		// Create vanilla SnuggleEngine and new SnuggleSession
		SnuggleEngine engine = new SnuggleEngine();
		SnuggleSession session = engine.createSession();

		// Parse some very basic Math Mode input
		SnuggleInput input = new SnuggleInput("$$ " + problem.getProblem() + " $$");
		try {
			session.parseInput(input);
		} catch (IOException e) {
			e.printStackTrace();
		}

		// Convert the results to an XML String, which in this case will
		// be a single MathML <math>...</math> element.
		String xmlString = session.buildXMLString();
		
		return xmlString;
	}
	
	public String makeImage(String s){
		// Create vanilla SnuggleEngine and new SnuggleSession
		SnuggleEngine engine = new SnuggleEngine();
		SnuggleSession session = engine.createSession();

		// Parse some very basic Math Mode input
		SnuggleInput input = new SnuggleInput("$$ " + s + " $$");
		try {
			session.parseInput(input);
		} catch (IOException e) {
			e.printStackTrace();
		}

		// Convert the results to an XML String, which in this case will
		// be a single MathML <math>...</math> element.
		String xmlString = session.buildXMLString();
		
		return xmlString;
	}
}
